home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
asmutil
/
a86v400.zip
/
A11.DOC
< prev
next >
Wrap
Text File
|
1994-12-21
|
31KB
|
824 lines
CHAPTER 11 MACROS AND CONDITIONAL ASSEMBLY
Macro Facility
A86 contains an easy-to-use, but very powerful macro facility.
The facility subsumes the capabilities of most assemblers,
including operand concatenation, repeat, indefinite repeat (often
called IRP), indefinite repeat character (IRPC), passing macro
operands by text or by value, comparing macro operands to
strings, and detecting blank macro operands. Unlike other
assemblers, A86 integrates these functions into the main macro
facility; so they can be invoked without clumsy syntax, or
strange characters in the macro-call operands.
Simple Macro Syntax
All macros must be defined before they are used. A macro
definition consists of the name of the macro, followed by the
word MACRO, followed by the text of the macro, followed by #EM,
which marks the end of the macro.
Many assembly languages require a list of dummy operand names to
follow the word MACRO. A86 does not: the operands are denoted in
the text with the fixed names #1, #2, #3, ... up to a limit of
#9, for each operand in order. If there is anything following
the word MACRO, it is considered part of the macro text.
Examples:
; CLEAR sets the register operand to zero.
CLEAR MACRO SUB #1,#1 #EM
CLEAR AX ; generates a SUB AX,AX instruction
CLEAR BX ; generates a SUB BX,BX instruction
; MOVM moves the second operand to the first operand.
; Both operands can be memory variables.
MOVM MACRO
MOV AL,#2
MOV #1,AL
#EM
VAR1 DB ?
VAR2 DB ?
MOVM VAR1,VAR2 ; generates MOV AL,VAR2 followed by MOV VAR1,AL
11-2
Formatting in Macro Definitions and Calls
The format of a macro definition is flexible. If the macro text
consists of a single instruction, the definition can be given in
a single line, as in the CLEAR macro given above. There is no
particular advantage to doing this, however: A86 prunes all
unnecessary spaces, blank lines, and comments from the macro text
before entering the text into the symbol table. I recommend the
more spread-out format of the MOVM macro, for program
readability.
All special macro operators within a macro definition begin with
a hash sign # (a hex 23 byte). The letters following the hash
sign can be given in either upper case or lower case. Hash-sign
operators are recognized even within quoted strings. If you wish
the hash sign to be treated literally, and not as the start of a
special macro operator, you must give 2 consecutive hash signs:
##. For example:
FOO MACRO
DB '##1'
DB '#1'
#em
FOO abc ; produces DB '#1' followed by DB 'abc'
The format of the macro call line is also flexible. A macro call
consists of the name of the macro, followed by the operands to be
plugged into the macro. A86 prunes leading and trailing blanks
from the operands of a macro call. The operands to a macro call
are always separated by commas. Also, as in all A86 source
lines, a semi-colon occurring outside of a quoted string is the
start of a comment, ignored by A86. If you want to include
commas, blanks, or semi-colons in your operands, you must enclose
your operand in single quotes.
Macro Operand Substitution
Some macro assemblers expect the operands to macro calls to
follow the same syntax as the operands to instructions. In those
assemblers, the operands are parsed, and reduced to numeric
values before being plugged into the macro definition text. This
is called "passing by value". As its default, A86 does not pass
by value, it passes by text. The only parsing of operands done
by the macro processor is to determine the start and the finish
of the operand text. That text is substituted, without regard
for its contents, for the "#n" that appears in the macro
definition. The text is interpreted by A86 only after a complete
line is expanded and as it is assembled.
11-3
If the first non-blank character after the macro name is a comma,
then the first operand is null: any occurrences of #1 in the
macro text will be deleted, and replaced with nothing. Likewise,
any two consecutive commas with no non-blanks between them will
result in the corresponding null operand. Also, out-of-range
operands are null; for example, #3 is a null operand if only two
operands are provided in the call.
Null operands to macros are not in themselves illegal. They will
produce errors only if the resulting macro expansion is illegal.
The method of passing by text allows operand text to be plugged
anywhere into a macro, even within symbol names. For example:
; KF_ENTRY creates an entry in the KFUNCS table, consisting of a
; pointer to a KF_ action routine. It also declares the
; corresponding CF_ symbol, which is the index within the table
; for that entry.
KF_ENTRY MACRO
CF_#1 EQU ($-KFUNCS)/2+080
DW KF_#1
#EM
KFUNCS:
KF_ENTRY UP
KF_ENTRY DOWN
; The above code is equivalent to:
;
; KFUNCS:
; DW KF_UP
; DW KF_DOWN
;
; CF_UP EQU 080
; CF_DOWN EQU 081
Quoted String Operands
As mentioned before, if you want to include blanks, commas, or
semicolons in your operands, you enclose the operand in single
quotes. In the vast majority of cases in which these special
characters need to be part of operands, the user wants them to be
quoted in the final, assembled line also. Therefore, the quotes
are passed in the operand. To override this, and strip the
quotes from the string, you precede the quoted string with a hash
sign. Examples:
11-4
DBW MACRO
DB #1
DW #2
#EM
DBW 'E', E_POINTER
DBW 'W', W_POINTER
; note that if quotes were not passed, the above lines would have
; to be DBW '''E''', E_POINTER; DBW '''W''', W_POINTER
FETCH_CHAR MACRO
LODSB
#1
CALL PROCESS_CHAR
#EM
FETCH_CHAR STOSB ; generates STOSB as second instruction
FETCH_CHAR #'INC DI' ; generates INC DI as second instruction
Looping by Operands in Macros
A86's macro facility contains two kinds of loops: you can loop
once for each operand in a range of operands; or you can loop
once for each character within an operand. The first kind of
loop, the R-loop, is discussed in this section; the second kind,
the C-loop, is discussed later.
An R-loop is a stretch of macro-definition code that is repeated
when the macro is expanded. In addition to the fixed operands #1
through #9, you can specify a variable operand, whose number
changes each time through the loop. You give the variable
operand one of the 4 names #W, #X, #Y, or #Z.
An R-loop begins with #R, followed immediately by the letter
W,X,Y, or Z naming the variable, followed by the number of the
first operand to be used, followed by the number of the last
operand to be used. After the #Rxnn is the text to be repeated.
The R-loop ends with #ER. For example:
STORE3 MACRO
MOV AX,#1
#RY24 ; "repeat for Y running from 2 through 4"
MOV #Y,AX
#ER
#EM
STORE3 VAR1,VAR2,VAR3,VAR4
; the above call produces the 4 instructions MOV AX,VAR1; MOV VAR2,AX;
; MOV VAR3,AX; MOV VAR4,AX.
11-5
The #L Last Operator and Indefinite Repeats
A86 recognizes the special operator #L, which is the last operand
in a macro call. #L can appear anywhere in macro text; but its
big power occurs in conjunction with R-loops, to yield an
indefinite-repeat facility.
A common example is as follows: you can take any macro that is
designed for one operand, and easily convert it into a macro that
accepts any number of operands. You do this by placing the
command #RX1L, "repeat for X running from 1 through L", at the
start of the macro, and the command #ER at the end just before
the #EM. Finally, you replace all instances of #1 in the macro
with #X. We see how this works with the CLEAR macro:
CLEAR MACRO #RX1L
SUB #X,#X
#ER
#EM